home *** CD-ROM | disk | FTP | other *** search
- /*
- * Atari ST-specific functions
- * written by Rob Janssen, PE1CHL
- * 3 configurations are possible:
- * .TOS
- * .ACC define GEM and GEMACC
- * .PRG define GEM and GEMPRG
- */
-
- #include <stdio.h>
- #include <ctype.h>
- #ifdef MWC
- # include <osbind.h> /* os interface defines */
- # define Kbshift Getshift /* MW goofed... */
- #endif
- #ifdef __TURBOC__
- # define cdecl
- # include <tos.h> /* os interface defines */
- #endif
- #include <linea.h> /* line-A interface defines */
- #include <time.h>
-
- #ifdef __TURBOC__ /* line-A access for Turbo C */
- # define VPLANES Linea->v_planes
- # define V_CEL_HT Vdiesc->v_cel_ht
- # define V_CEL_MX Vdiesc->v_cel_mx
- # define V_CEL_MY Vdiesc->v_cel_my
- # define V_CUR_AD ((char *) (Vdiesc->v_cur_ad))
- # define V_CUR_OFF Vdiesc->v_cur_off
- # define V_CUR_CX Vdiesc->v_cur_xy[0]
- # define V_CUR_CY Vdiesc->v_cur_xy[1]
- # define V_FNT_AD ((char *) (Vdiesc->v_fnt_ad))
- #endif
-
- #include "global.h"
- #include "config.h"
- #include "mbuf.h"
- #include "internet.h"
- #include "iface.h"
- #include "atari.h"
- #include "timer.h"
- #include "environ.h"
-
- extern unsigned nasy;
-
- /* Interface list header */
- struct interface *ifaces;
-
- #ifdef OUTBUF
- static char *ttbuf;
- #endif
-
- int auxcon = 0; /* auxcon control word */
- #define AUXCOUT 0x01 /* send out to AUX */
- #define AUXCNOT 0x02 /* don't send out to screen */
- #define AUXCIN 0x10 /* read input from AUX */
- int auxitrn[256]; /* aux input translate table */
- char auxotrn[256]; /* aux output translate table */
-
- int screenmode = 0; /* screen output control word */
- #define SCRTOS 0 /* output via TOS */
- #define SCRBIOS 1 /* output via BIOS */
- #define SCRDIR 2 /* direct output to screen */
-
- extern void trap_x(); /* handler for trap #5/#11 */
- void (*trap_x_save)(); /* saved trap #5/#11 handler */
-
- extern char startup[]; /* startup file name */
-
- extern FILE *logfp; /* log file pointer */
- extern char logname[]; /* log file name */
-
- extern FILE *trfp; /* trace file pointer */
- extern char trname[]; /* trace file name */
-
- #ifdef GEM
-
- #define WORD int /* signed word (16 bits) */
- #define TRUE (1) /* TRUE value */
- #define FALSE (0) /* FALSE value */
-
- #include <gemdefs.h> /* MW GEM definitions */
- #include <obdefs.h>
-
- #define MAXWIN 8 /* maximal window handle from GEM */
- #define USEWIN 2 /* windows used by this application */
-
- #define DESK 0 /* window number for desktop */
- #define ALIGN(x,n) (x) = (n * (((x) + (n / 2)) / n))/* align x to n incr. */
-
- #define WI_KIND (HSLIDE|RTARROW|LFARROW|VSLIDE|DNARROW|UPARROW|SIZER|MOVER|FULLER|CLOSER|NAME)
-
- #define MIN_WIDTH (16 * gr_hwbox) /* minimal window width */
- #define MIN_HEIGHT (5 * gr_hhbox) /* minimal window height */
-
- #define MAXLINE 100 /* history lines saved */
- #define MAXCHAR 80 /* max characters on each line */
-
- /*** datatypes ***/
-
- typedef struct linehist /* define 'line history' type */
- {
- struct linehist *next; /* forward link */
- struct linehist *prev; /* backward link */
- int len; /* this one's length */
- char line[1]; /* the actual line to be stored */
- } LINEHIST;
-
- typedef struct /* define 'sliding window' type */
- {
- long total; /* total size in this dimension */
- long pos; /* pos of portion currently seen */
- int seen; /* size of portion currently seen */
- } SLWIN;
-
- typedef struct window /* info about windows */
- {
- WORD win; /* corresponding window handle */
- WORD kind; /* this window's wi_kind */
- WORD pobj; /* object selected there */
- GRECT work; /* work area pos/size */
- GRECT full; /* full size of window */
- GRECT org; /* originating pos/size for shrink */
- SLWIN hori; /* horizontal slider info */
- SLWIN vert; /* vertical slider info */
- LINEHIST *head; /* head of line history */
- LINEHIST *tail; /* tail of line history */
- int curpos; /* position on current line */
- char curline[MAXCHAR + 1]; /* current line */
- char cursor; /* cursor state */
- char open; /* window opened? */
- char title[MAX_LEN]; /* window title (if any) */
- char info[MAX_LEN]; /* window info (if any) */
- } WINDOW;
-
- /*** GLOBAL VARIABLES ***/
-
- /* GEM handles, information and the like */
-
- extern WORD gl_apid; /* application id (external to MWC) */
- WORD gl_mnid; /* menu id for this accessory */
- WORD gr_handle; /* physical workstation handle */
- static WORD handle; /* virtual workstation handle */
-
- WORD gr_hhchar,gr_hwchar,gr_hhbox,gr_hwbox;/* system font sizes */
-
- /* window management datastructures */
-
- static WINDOW window[USEWIN]; /* window info, DESK + user windows */
- static WORD win[MAXWIN]; /* handle to application conv. */
- static WORD topwin = -1; /* top (=current) window handle */
-
- static WORD await = MU_MESAG|MU_TIMER; /* select initially active events */
- static GRECT m1,m2; /* mouse event rectangles */
- static WORD m1flag,m2flag; /* flags for mouse events 1,2 */
-
- static WORD keyqueue = 0; /* last typed character */
- static WORD keyqstat = 0; /* it's shift status */
- static WORD fastpoll = 50; /* fast poll interval */
-
- WORD work_in[] = {1,1,1,1,1,1,1,1,1,1,2};/* Input to GSX parameter array */
- WORD work_out[57]; /* Output from GSX parameter array */
-
- WORD contrl[12]; /* storage wasted for bindings */
- WORD intin[128];
- WORD ptsin[128];
- WORD intout[128];
- WORD ptsout[128];
-
- /* the resource file symbols */
-
- #ifdef GEMPRG
- # include "atari_rs.h"
- extern OBJECT *rs_trindex[];
- #endif
-
- /* forward declarations (when necessary) */
-
- void pop_up();
- void wi_getwork();
- void wi_close();
- void sl_update();
- void rq_redraw();
- WORD do_form();
- WORD *rc2pts();
- int wputc();
-
- #else /* not GEM */
-
- # define CONTERM *((char *) 0x484L) /* system's conterm byte */
- char sconterm; /* saved conterm byte */
-
- char *logbase; /* logical screen base */
-
- int cursor = 1; /* cursor currently visible? */
- # ifdef MWC
- extern int _fputt(); /* standard output putc routine */
- # endif
- #endif
-
- #ifndef GEMACC
- # ifdef MWC
- long *_stksize = (long *) 4096; /* stack size in bytes, becomes ptr */
- # define STACK _stksize
- # endif
- # ifdef __TURBOC__
- extern long *_StkLim; /* initialized to stack limit */
- # define STACK _StkLim
- # endif
-
- # define STKMAGIC 0x31415927L /* magic to check overflow */
- #endif
-
- void eihalt();
-
- #ifndef GEMACC
- #ifdef __TURBOC__
- static void watchtick(void,...); /* function called at timer tick */
- static void (*orgtick)(void,...); /* original timertick handler */
- #else
- static void watchtick(); /* function called at timer tick */
- static void (*orgtick)(); /* original timertick handler */
- #endif
- static long watchcnt; /* actual watchdog counter */
- static long watchnet; /* watchdog while in NET */
- static long watchsh; /* watchdog while in SHELL */
- static unsigned watchhw; /* watchdog hardware reset */
- #endif
-
- static void lat_start(),lat_stop(),lat_raw(),lat_status();
-
-
- /* Called at startup time to set up console I/O, memory heap */
- /* also sets and saves lots of other things on the Atari.... */
-
- ioinit()
- {
- #ifdef GEM
- WORD d;
- # ifdef GEMACC
- char net[30];
- # endif
- #else
- long sav_ssp; /* saved stackpointer for Super() */
- #endif
-
- #if (defined(MWC) && (MWC < 300)) /* pre-3.0 MW C? */
- /* set the handler for trap #5. this will be called using the */
- /* micro_rtx() function, and will disable/enable interrupts */
- trap_x_save = (void (*)()) Setexc(0x25,trap_x);
- #else
- /* set the handler for trap #7. this will be called using the */
- /* _VtrapB_() function, and will disable/enable interrupts */
- trap_x_save = (void (*)()) Setexc(0x27,trap_x);
- #endif
-
- #ifndef GEMACC
- STACK[0] = STACK[16] = /* mark stack for overflow check */
- STACK[32] = STKMAGIC;
-
- orgtick = (void (*)()) Setexc(0x100,watchtick); /* install watchdog ticker */
- #endif
-
- #if (OUTBUF && !GEM)
- ttbuf = malloc(BUFSIZ);
- setbuf(stdout,ttbuf);
- #endif
-
- #ifdef GEM
- /* re-route output from "stdout" to window handler */
-
- stdout->_pt = wputc; /* character output handler */
- stdout->_ff |= _FERR; /* to disable fflush() */
-
- if (!appl_init() || gl_apid < 0) /* init application */
- exit(1); /* exit if error (fatal) */
-
- gr_handle = graf_handle(&gr_hwchar,&gr_hhchar,&gr_hwbox,&gr_hhbox);
-
- handle = gr_handle; /* open virtual workstation */
- v_opnvwk(work_in,&handle,work_out); /* handle:=virtual ws handle */
-
- vst_alignment(handle,0,5,&d,&d); /* set text alignment */
-
- # ifdef GEMPRG
- rsrc_fixup(); /* fix the in-memory resource */
- menu_bar(rs_trindex[MENUBAR],TRUE); /* show the menu bar */
- # endif
-
- # ifdef GEMACC
- if ((gl_mnid = menu_register(gl_apid, " KA9Q TCP/IP Net ")) < 0)
- exit(2);
- # endif
-
- window[0].win = DESK; /* init desktop window descr. */
- window[0].open = TRUE;
- wi_getwork(0); /* get workarea of desktop */
- win[DESK] = 0; /* remember it's handle */
-
- # ifdef GEMPRG
- rs_trindex[BACKDROP][ROOT].ob_x = window[DESK].work.g_x;/* set size to full desktop */
- rs_trindex[BACKDROP][ROOT].ob_y = window[DESK].work.g_y;
- rs_trindex[BACKDROP][ROOT].ob_width = window[DESK].work.g_w;
- rs_trindex[BACKDROP][ROOT].ob_height = window[DESK].work.g_h;
-
- ob_draw(DESK,rs_trindex[BACKDROP],ROOT); /* draw the backdrop */
-
- wind_set(DESK,WF_NEWDESK,rs_trindex[BACKDROP],ROOT);
- # endif
-
- window[1].hori.total = MAXCHAR; /* init window 1 description */
- window[1].vert.total = 1; /* always one current line... */
-
- m1.g_x = m1.g_y = m1.g_w = m1.g_h = /* no mouse event #1 */
- m2.g_x = m2.g_y = m2.g_w = m2.g_h = /* no mouse event #2 */
- m1flag = m2flag = 0; /* dummy flag (entry) */
-
- # ifdef GEMACC
- for (d = 0; d < 50; d++) /* allow others to initialize */
- eihalt();
- # endif
-
- # ifdef GEMPRG
- pop_up();
- graf_mouse(ARROW); /* default mouse form */
- # endif
-
- # ifdef GEMACC
- if ((d = Dgetdrv()) >= 2) /* a harddisk system? (??) */
- {
- strcpy(net,startup); /* find startup file */
-
- do
- {
- net[0] = d + 'a'; /* try C-P */
- } while (access(net,4) && ((++d < 16) || (d = 0)));
-
- Dsetdrv(d); /* move to where it's found */
- }
- # endif
- #else /* not GEM */
- sav_ssp = Super(NULL); /* switch to supervisor mode */
- sconterm = CONTERM; /* read present console flags */
- CONTERM |= 0x08; /* set the "return shift state" flag */
- Super(sav_ssp); /* switch-back to user mode */
- #endif
-
- atari_init('n'); /* general initialization */
- }
-
- /* Called just before exiting to restore console state (and others)
- */
-
- iostop()
- {
- long sav_ssp; /* saved stackpointer for Super() */
- #ifdef GEMPRG
- WORD wi;
-
- graf_mouse(HOURGLASS); /* revert to 'wait' mouseform */
-
- for (wi = 1; wi < MAXWIN; wi++) /* close the windows */
- if (win[wi] != 0) /* when they are in use */
- wi_close(wi);
-
- menu_bar(rs_trindex[MENUBAR],FALSE); /* remove the menubar */
- v_clsvwk(handle); /* close virtual workstation */
- appl_exit(); /* exit from application */
- #endif
-
- #if (OUTBUF && !GEM)
- setbuf(stdout,NULLCHAR);
- free(ttbuf);
- #endif
- while(ifaces != NULLIF){
- /* first flush the interface's buffers */
- while(ifaces->recv != NULLVFP && (*ifaces->recv)(ifaces))
- ;
- if(ifaces->stop != NULLFP)
- (*ifaces->stop)(ifaces);
- ifaces = ifaces->next;
- }
-
- #ifndef GEM
- while (kbread() != -1) /* eat remaining chars, cursor ON */
- ;
-
- sav_ssp = Super(NULL); /* switch to supervisor mode */
- CONTERM = sconterm; /* restore value saved at startup */
- Super(sav_ssp); /* switch-back to user mode */
- #endif
-
- atari_stop(); /* general termination */
-
- lat_stop(); /* stop latency measurement */
-
- #ifndef GEMACC
- Setexc(0x100,orgtick); /* restore original timer tick */
- #endif
- #if (defined(MWC) && (MWC < 300)) /* pre-3.0 MW C? */
- Setexc(0x25,trap_x_save); /* remove our trap #5 handler */
- #else
- Setexc(0x27,trap_x_save); /* remove our trap #7 handler */
- #endif
-
- sav_ssp = Super(NULL); /* switch to supervisor mode */
- *((long *) 0x3fc) = 0x0L; /* erase signature (see log proc) */
- Super(sav_ssp); /* switch-back to user mode */
- }
-
- /* checks the time then ticks and updates ISS */
- void
- check_time()
- {
- int32 iss();
- int maxticks = (int) SEC2TICK(15); /* upper limit on delayed ticks */
- static unsigned long clkval = 0;
-
- #ifndef NOCLOCK
- clock_t clknow = clock() / 20L; /* ANSI routine to read clock */
- #else
- long sav_ssp; /* saved stackpointer for Super() */
- unsigned long clknow; /* current clock value */
-
- sav_ssp = Super(NULL); /* switch to supervisor mode */
- clknow = *((unsigned long *) 0x4baL) / 20L; /* read 200Hz timer value, make 10/sec */
- Super(sav_ssp); /* switch-back to user mode */
- #endif
-
- if (clkval == 0) /* first time? */
- clkval = clknow;
-
- while(clkval < clknow){
- #ifdef IP
- icmpclk(); /* Call this one before tick */
- #endif
- tick();
- #ifdef IP
- (void)iss();
- #endif
- if (maxticks--) /* check a limit on ticks */
- clkval++;
- else
- clkval = clknow; /* thereafter, ignore them */
- }
- }
-
- #ifdef MWC
- /* Mark Williams C reads the keyboard clock on the first call to time() */
- /* using the Kgettime() routine. Unfortunately, this clock has moved to */
- /* a different place in the Mega ST, so we'll redefine Kgettime to call */
- /* the xbios routine that will read both the clocks (MW should do that!)*/
-
- tm_t *Kgettime ()
-
- {
- static tm_t rv; /* returned value is static struct */
- register tetd_t tim; /* value from xbios */
-
- tim = Gettime(); /* reads keyboard or RTC chip */
-
- rv.tm_sec = (tim & 0x1f) * 2; /* silly 2-second time increment */
- rv.tm_min = (tim >> 5) & 0x3f;
- rv.tm_hour = (tim >> 11) & 0x1f;
- rv.tm_mday = (tim >> 16) & 0x1f;
- rv.tm_mon = ((tim >> 21) & 0x0f) - 1;
- rv.tm_year = ((tim >> 25) & 0x7f) + 80;
- /* note: tm_wday, tm_yday and tm_isdst not set */
-
- return (&rv);
- }
- #endif
-
- /* Read characters from the keyboard, translating them to "real" ASCII
- * If none are ready, return -1
- */
- int
- kbread()
- {
- unsigned char key,scan,shift;
- int c;
- static int altkeys = 0; /* for alt-digit pressure */
- static int altchar = 0;
- #ifdef GEM
- int x,y;
- register WINDOW *curwin;
- char outstr[4];
- #else
- long keychar;
- #endif
-
- if (auxcon & AUXCIN) /* check the aux port for chars? */
- {
- if (Bconstat(1)) /* a character ready? */
- return (auxitrn[uchar(Bconin(1))]); /* read it and translate */
- }
-
- #ifdef GEM
- if (!keyqueue) /* no char typed? */
- {
- if (topwin > 0 && win[topwin]) /* our window on top? */
- {
- curwin = &window[win[topwin]];
-
- if (curwin->open && !curwin->cursor &&
- curwin->curpos >= curwin->hori.pos &&
- (y = curwin->vert.total -
- curwin->vert.pos - 1) <= curwin->vert.seen)
- {
- vs_clip(handle,TRUE,rc2pts(&curwin->work));
-
- x = curwin->work.g_x + 1 +
- (curwin->curpos - curwin->hori.pos) * gr_hwchar;
-
- y = curwin->work.g_y + y * gr_hhchar;
-
- outstr[0] = 240; /* cursor char */
- outstr[1] = ' ';
- outstr[2] = '\0';
- v_gtext(handle,x,y,outstr);
-
- curwin->cursor = 1;
- }
- }
-
- return (-1);
- }
-
- key = keyqueue; /* get ascii part */
- scan = keyqueue >> 8; /* get scancode */
- shift = keyqstat & 0x1f; /* get shift status */
- keyqueue = keyqstat = 0; /* keycode used, clear it */
- #else
- if (!Cconis()){ /* any char available? */
- if (!(Kbshift(-1) & 0x08)){ /* no, Alternate not pressed? */
- if (altkeys){
- c = altchar;
- altchar = altkeys = 0;
- return (c);
- }
- }
- if (!cursor){ /* cursor visible? */
- cursor = 1;
- Bconout(2,'\033'); /* no, switch it on */
- Bconout(2,'e');
- }
- return (-1); /* return -1 for 'no chars' */
- }
-
- keychar = Crawcin(); /* read char, no echo */
- key = keychar; /* get ascii part */
- scan = keychar >> 16; /* get scancode */
- shift = (keychar >> 24) & 0x1f; /* get shift status */
- #endif
-
- if ((shift & 0x08) && /* Alternate key pressed? */
- scan >= 103 && scan <= 112 && /* numeric keypad entry */
- key >= '0' && key <= '9') /* more verification of numeric */
- {
- altchar = 10 * altchar + key - '0'; /* compute code */
-
- if (++altkeys == 3){ /* code complete? */
- c = altchar;
- altchar = altkeys = 0;
- return (c);
- } else {
- return (-1); /* incomplete, return no char */
- }
- }
-
- altchar = altkeys = 0; /* no Alt - wipe Alternate char */
-
- if((c = key) == 0){
- /* a special char */
- switch(scan) /* examine scancode */
- {
- case 3: /* NULL (bizzare!) */
- c = 0;
- break;
- case 59: /* F-1 key */
- c = -11;
- break;
- case 60: /* F-2 key */
- c = -10;
- break;
- case 61: /* F-3 key */
- c = -9;
- break;
- case 62: /* F-4 key */
- c = -8;
- break;
- case 63: /* F-5 key */
- c = -7;
- break;
- case 64: /* F-6 key */
- c = -6;
- break;
- case 65: /* F-7 key */
- c = -5;
- break;
- case 66: /* F-8 key */
- c = -4;
- break;
- case 67: /* F-9 key */
- c = -3;
- break;
- case 68: /* F-10 key (used as command-mode escape) */
- c = -2;
- break;
- case 71: /* HOME key */
- c = -20;
- break;
- case 72: /* UP arrow */
- c = -19;
- break;
- case 73: /* PAGE UP */
- case 98: /* HELP key (used as PAGE UP) */
- c = -18;
- break;
- case 75: /* LEFT arrow */
- c = -17;
- break;
- case 77: /* RIGHT arrow */
- c = -16;
- break;
- case 119: /* END (ctrl-Home) key */
- c = -15;
- break;
- case 80: /* DOWN arrow */
- c = -14;
- break;
- case 81: /* PAGE DOWN */
- case 97: /* UNDO key (used as PAGE DOWN) */
- c = -13;
- break;
- case 82: /* INS key */
- c = -12;
- break;
- case 83: /* DEL key */
- c = 0x7f;
- break;
- default: /* Dunno what it is */
- c = -1;
- }
- }
-
- return (c);
- }
-
- #ifdef GEM
- /* utility routines only needed for GEM version */
-
- /*** elementary window management routines ***/
-
- /* align window in such a way that first character inside it starts */
- /* on a byte boundary. a somewhat specialized function... */
-
- void wi_align (rc)
- register GRECT *rc; /* window outside dimensions */
-
- {
- /* first, calculate work area */
-
- wind_calc(1,WI_KIND,rc->g_x,rc->g_y,rc->g_w,rc->g_h,
- &rc->g_x,&rc->g_y,&rc->g_w,&rc->g_h);
-
- ALIGN(rc->g_x,8); /* align on 8-bit boundary */
-
- if (--(rc->g_x) < 0) /* one bit extra, left of char */
- rc->g_x += 8; /* if that makes it negative, bump */
-
- ALIGN(rc->g_w,gr_hwchar); /* integer number of chars wide */
- rc->g_w++; /* one extra (left of first char) */
-
- ALIGN(rc->g_h,gr_hhchar); /* integer number of lines high */
-
- /* re-calculate outside dimensions */
-
- wind_calc(0,WI_KIND,rc->g_x,rc->g_y,rc->g_w,rc->g_h,
- &rc->g_x,&rc->g_y,&rc->g_w,&rc->g_h);
- }
-
- /* create and open a window, and update window datatructure */
- /* return TRUE when the window could be created and opened */
- /* assumes some fields of window[wi_num] already set up: */
- /* title,info,org */
-
- int wi_open (wi_num,kind,wsize)
- WORD wi_num; /* window NUMBER */
- WORD kind; /* window kind */
- register GRECT *wsize; /* desired pos/size rc */
-
- {
- register WINDOW *curwin = &window[wi_num];
- GRECT rc;
- WORD pts[4]; /* dummy for clip_off */
-
- if (!curwin->open) /* not yet open? */
- {
- curwin->kind = kind; /* remember kind of window */
-
- graf_growbox(curwin->org.g_x,curwin->org.g_y,
- curwin->org.g_w,curwin->org.g_h,
- wsize->g_x,wsize->g_y,wsize->g_w,wsize->g_h);
-
- rc_copy(&window[0].work,&curwin->full);/* max size is desksize */
- wi_align(&curwin->full); /* but, aligned to char bound */
-
- curwin->full.g_y = window[0].work.g_y +
- (window[0].work.g_h - curwin->full.g_h) / 2;
-
- while (curwin->full.g_x + curwin->full.g_w >
- window[0].work.g_x + window[0].work.g_w)
- curwin->full.g_w -= gr_hwchar; /* make sure it will fit on desktop */
-
- if ((curwin->win = wind_create(curwin->kind,curwin->full.g_x,
- curwin->full.g_y,
- curwin->full.g_w,
- curwin->full.g_h)) < 0)
- {
- form_alert(1,"[3][|No more windows available][ SORRY ]");
- return (FALSE);
- }
-
- if (curwin->win >= MAXWIN) /* unexpected window number? */
- {
- form_alert(1,"[3][|Unexpected window handle][ SORRY ]");
- wind_delete(curwin->win); /* destroy bad window */
- return (FALSE);
- }
-
- win[curwin->win] = wi_num; /* remember number for handle */
-
- wind_set(curwin->win,WF_NAME,curwin->title);/* effectuate title */
- wind_set(curwin->win,WF_INFO,curwin->info);/* effectuate info */
-
- wind_set(curwin->win,WF_HSLSIZE,1000);/* initially, full sliders */
- wind_set(curwin->win,WF_VSLSIZE,1000);
-
- wind_update(BEG_UPDATE); /* lock rectangle list */
-
- wind_open(curwin->win,wsize->g_x,wsize->g_y,/* actually open the window */
- wsize->g_w,wsize->g_h);
-
- curwin->open = TRUE; /* remember it is open */
- topwin = curwin->win; /* it always comes on top */
-
- wi_getwork(curwin->win); /* get size/pos info */
- sl_update(curwin->win); /* set sliders */
-
- rc_copy(&curwin->work,&rc); /* get window workarea */
- if (rc_intersect(&window[0].work,&rc))/* intersect with desktop */
- {
- vs_clip(handle,FALSE,pts); /* clip off for speed */
- vsf_interior(handle,0); /* blank the work area */
- vr_recfl(handle,rc2pts(&rc));
- }
-
- wind_update(END_UPDATE); /* unlock rectangle list */
- }
-
- return (TRUE); /* results okay! */
- }
-
- /* close a window and update window datatructure */
-
- void wi_close (wi)
- WORD wi; /* window handle */
-
- {
- register WINDOW *curwin = &window[win[wi]];
- WORD d; /* dummy for wind_get */
-
- if (curwin->open) /* now open? */
- {
- wind_close(wi); /* close the window */
-
- graf_shrinkbox(curwin->org.g_x,curwin->org.g_y,
- curwin->org.g_w,curwin->org.g_h,
- curwin->work.g_x,curwin->work.g_y,
- curwin->work.g_w,curwin->work.g_h);
-
- if (wi == topwin) /* was it the top window? */
- wind_get(0,WF_TOP,&topwin,&d,&d,&d);/* get new top window */
-
- wind_delete(wi); /* delete window */
-
- curwin->open = FALSE; /* remember it is closed */
- win[wi] = 0; /* also forget the handle */
- }
- }
-
- /* get a window's current size and position */
- /* also sets amount seen for sliding scrollbars */
-
- void wi_getwork (wi)
- WORD wi;
-
- {
- register WINDOW *curwin = &window[win[wi]];
-
- wind_get(wi,WF_WORKXYWH, /* get size and position info */
- &curwin->work.g_x,&curwin->work.g_y,
- &curwin->work.g_w,&curwin->work.g_h);
-
- /* set the 'amount seen' for each window */
-
- switch (win[wi]) /* determine application usage */
- {
- case 1: /* output window */
- curwin->hori.seen = curwin->work.g_w / gr_hwchar;
- curwin->vert.seen = curwin->work.g_h / gr_hhchar;
- break;
- }
- }
-
- /* window character-handling routines */
-
- /* linefeed adds another line to the history, and updates window (scroll) */
-
- static void linefeed (curwin)
- register WINDOW *curwin;
-
- {
- register LINEHIST *new;
-
- if (curwin->vert.total > MAXLINE) /* above the maximum? */
- {
- if (curwin->head != NULL) /* should be! */
- {
- free(curwin->head); /* release it */
- curwin->head = curwin->head->next;
- curwin->head->prev = NULL;
- curwin->vert.total--;
- }
- }
-
- curwin->curline[curwin->curpos] = '\0';
-
- if ((new = malloc(sizeof(LINEHIST) + curwin->curpos)) == NULL)
- return; /* that's pity! */
-
- new->len = curwin->curpos;
- strcpy(new->line,curwin->curline);
-
- if (curwin->tail == NULL)
- {
- curwin->head = curwin->tail = new;
- new->prev = new->next = NULL;
- }
- else
- {
- new->prev = curwin->tail;
- new->next = NULL;
- curwin->tail->next = new;
- curwin->tail = new;
- }
-
- curwin->vert.total++;
-
- if (curwin->vert.pos >= curwin->vert.total - curwin->vert.seen - 1)
- curwin->vert.pos = curwin->vert.total - curwin->vert.seen;
-
- curwin->curpos = 0;
-
- sl_update(curwin->win); /* update sliders */
-
- if (curwin->vert.pos >= curwin->vert.total - curwin->vert.seen)
- {
- rq_redraw(curwin->win,&curwin->work); /* draw desired window */
- eihalt(); /* handle messages */
- }
- }
-
- /* write a character to a window */
-
- int wputc (c,outfile)
- int c;
- FILE *outfile;
-
- {
- int wdw;
- WORD x,y;
- register WINDOW *curwin;
- char outstr[2];
-
- if (outfile == stdout) /* determine window# from handle */
- {
- if (auxcon & AUXCOUT) /* standard output to AUX too? */
- {
- if (c == '\n') /* if \n, add \r */
- Bconout(1,auxotrn['\r']);
-
- Bconout(1,auxotrn[uchar(c)]); /* send (translated) character */
- }
-
- if (auxcon & AUXCNOT) /* not to screen? */
- return; /* then we're done! */
-
- wdw = 1; /* also to window 1 */
- }
- else
- return (EOF);
-
- curwin = &window[wdw]; /* address output window */
-
- switch(c) /* character interpreter */
- {
- case '\b': if (curwin->curpos) /* backspace */
- curwin->curpos--;
-
- break;
-
- case '\n': linefeed(curwin); /* linefeed */
- break;
-
- case '\r': break; /* carriage return */
-
- case '\t': do /* horizontal tab */
- {
- wputc(' ',outfile);
- } while (curwin->curpos % 8);
-
- break;
-
- case '\a': Bconout(2,7); /* bell */
- if (!auxcon)
- pop_up(); /* bring under close attention */
- break;
-
- case '\0': break; /* NUL */
-
- default: curwin->curline[curwin->curpos++] = c; /* some other char */
-
- if (curwin->curpos >= MAXCHAR) /* right margin? */
- linefeed(curwin); /* wrap to next line */
- else
- {
- if (topwin > 0 && win[topwin] == wdw &&
- curwin->curpos > curwin->hori.pos &&
- (y = curwin->vert.total -
- curwin->vert.pos - 1) <= curwin->vert.seen)
- {
- vs_clip(handle,TRUE,rc2pts(&curwin->work));
-
- x = curwin->work.g_x + 1 +
- (curwin->curpos - 1 - curwin->hori.pos) * gr_hwchar;
-
- y = curwin->work.g_y + y * gr_hhchar;
-
- outstr[0] = c;
- outstr[1] = '\0';
- v_gtext(handle,x,y,outstr);
- }
- else
- curwin->cursor = 2; /* must be updated */
- }
-
- break;
- }
-
- if (curwin->cursor != 2)
- curwin->cursor = 0; /* show cursor when needed */
-
- return (c);
- }
-
- /* rq_redraw: request to redraw an area by sending myself a redraw message */
-
- void rq_redraw (wi,area)
- WORD wi; /* window handle */
- register GRECT *area; /* area to redraw */
-
- {
- WORD msg[8]; /* buffer for message */
-
- msg[0] = WM_REDRAW; /* build a REDRAW message */
- msg[1] = gl_apid; /* coming from myself */
- msg[2] = 0; /* no more than std. 16 bytes */
- msg[3] = wi; /* redraw this window */
- msg[4] = area->g_x; /* area to redraw */
- msg[5] = area->g_y;
- msg[6] = area->g_w;
- msg[7] = area->g_h;
-
- appl_write(gl_apid,sizeof(msg),msg); /* send myself the message */
- }
-
- /*** the one-and-only window redraw routine ***/
-
- /* do_redraw: find and redraw all clipping rectangles in an area */
- /* only to be called when a redraw message comes in (use rq_redraw) */
-
- void do_redraw (wi,area)
- WORD wi; /* window handle */
- register GRECT *area; /* area to redraw */
-
- {
- register WINDOW *curwin = &window[win[wi]];
- GRECT rc; /* intersection area */
- WORD *pts;
- int y,skip;
- LINEHIST *lin;
- char m_off = FALSE; /* mouse already turned off? */
-
- if (!rc_intersect(&window[0].work,area))/* first intersect with desktop */
- return; /* nothing to do! (unlikely) */
-
- wind_update(BEG_UPDATE); /* lock rectangle list */
-
- /* get the first rectangle in the 'visible' list for this window */
-
- wind_get(wi,WF_FIRSTXYWH,&rc.g_x,&rc.g_y,&rc.g_w,&rc.g_h);
-
- while (rc.g_w && rc.g_h) /* got a rectangle? */
- {
- if (rc_intersect(area,&rc)) /* is there an intersection? */
- {
- if (!m_off) /* mouse already OFF? */
- {
- graf_mouse(M_OFF); /* mouse OFF during updates */
- m_off = TRUE; /* now it's off */
- }
-
- pts = rc2pts(&rc); /* convert inters. area to points */
-
- vs_clip(handle,FALSE,pts); /* clip off for speed */
- vsf_interior(handle,0); /* blank the area */
- vr_recfl(handle,pts);
-
- vs_clip(handle,TRUE,pts); /* clip on */
- y = curwin->work.g_y; /* top drawing position */
-
- if ((lin = curwin->tail) != NULL) /* lines in history? */
- {
- skip = curwin->vert.total - curwin->vert.pos - 1; /* lines to skip back */
-
- while (--skip && lin->prev != NULL)
- lin = lin->prev; /* work backwards */
- }
-
- while (lin != NULL) /* quit when all printed */
- {
- if (lin->len > curwin->hori.pos)
- v_gtext(handle,curwin->work.g_x + 1,y,
- lin->line + curwin->hori.pos);
-
- if ((y += gr_hhchar) > rc.g_y + rc.g_h)
- break;
-
- lin = lin->next;
- }
-
- /* if still space, also show current (partial) line */
-
- if (y <= rc.g_y + rc.g_h && curwin->curpos > curwin->hori.pos)
- {
- curwin->curline[curwin->curpos] = '\0';
- v_gtext(handle,curwin->work.g_x + 1,y,
- curwin->curline + curwin->hori.pos);
- }
- }
-
- wind_get(wi,WF_NEXTXYWH,&rc.g_x,&rc.g_y,&rc.g_w,&rc.g_h);
- }
-
- if (m_off) /* did we turn it OFF? */
- graf_mouse(M_ON); /* mouse can now be ON again */
-
- wind_update(END_UPDATE); /* unlock rectangle list */
- curwin->cursor = 0; /* should re-display cursor now */
- }
-
- /*
- * set the sliders as required.
- *
- * the SLWIN structures 'hori' and 'vert' are used as input.
- * inconsistencies in the position are corrected.
- * the sliders are only set when required.
- *
- */
-
- void sl_update (wi)
- WORD wi; /* window handle */
-
- {
- register WINDOW *curwin = &window[win[wi]];
- register WORD size,pos; /* computed size & position */
- register long maxpos; /* maximal position */
- WORD now,dummy; /* current value */
-
- if (curwin->kind & HSLIDE) /* horizontal slider in use? */
- {
- maxpos = curwin->hori.total - curwin->hori.seen;/* max allowed pos */
-
- if (curwin->hori.pos > maxpos) /* bring position within range */
- curwin->hori.pos = maxpos;
-
- if (curwin->hori.pos < 0)
- curwin->hori.pos = 0;
-
- if (curwin->hori.seen < curwin->hori.total)/* partial view? */
- {
- pos = (1000L * curwin->hori.pos) / maxpos;
- size = (1000L * curwin->hori.seen) / curwin->hori.total;
- }
- else /* we have full-view! */
- {
- pos = 0; /* set slider to full size */
- size = 1000;
- }
-
- wind_get(wi,WF_HSLIDE,&now,&dummy,&dummy,&dummy);/* get pos */
-
- if (pos != now) /* update needed? */
- wind_set(wi,WF_HSLIDE,pos); /* then do it */
-
- wind_get(wi,WF_HSLSIZE,&now,&dummy,&dummy,&dummy);/* get size */
-
- if (size != now) /* update needed? */
- wind_set(wi,WF_HSLSIZE,size); /* then do it */
- }
-
- if (curwin->kind & VSLIDE) /* vertical slider in use? */
- {
- maxpos = curwin->vert.total - curwin->vert.seen;/* max allowed pos */
-
- if (curwin->vert.pos > maxpos) /* bring position within range */
- curwin->vert.pos = maxpos;
-
- if (curwin->vert.pos < 0)
- curwin->vert.pos = 0;
-
- if (curwin->vert.seen < curwin->vert.total)/* partial view? */
- {
- pos = (1000L * curwin->vert.pos) / maxpos;
- size = (1000L * curwin->vert.seen) / curwin->vert.total;
- }
- else /* we have full-view! */
- {
- pos = 0; /* set slider to full size */
- size = 1000;
- }
-
- wind_get(wi,WF_VSLIDE,&now,&dummy,&dummy,&dummy);/* get pos */
-
- if (pos != now) /* update needed? */
- wind_set(wi,WF_VSLIDE,pos); /* then do it */
-
- wind_get(wi,WF_VSLSIZE,&now,&dummy,&dummy,&dummy);/* get size */
-
- if (size != now) /* update needed? */
- wind_set(wi,WF_VSLSIZE,size); /* then do it */
- }
- }
-
- # ifdef GEMPRG
- /* handle menu selections */
-
- void mn_select (menu_entry)
- WORD menu_entry; /* entry index */
-
- {
- GRECT text_rc; /* menu entry text x, y, w and h */
-
- switch (menu_entry) /* the menu entry index */
- {
- case ENABOUT: /* about this program... */
- ob_rect(rs_trindex[MENUBAR],ENABOUT,&text_rc);/* get menu entry info */
- do_form(rs_trindex[ABOUT],&text_rc);/* display 'ABOUT' dialogue */
- break;
-
- case ENOPEN: /* open window */
- pop_up();
- break;
-
- case ENQUIT: /* quit program */
- doexit(0);
- break;
- }
- }
-
- /*
- * display an input form, await respons,ttnd remove it
- * only the exitbox is deselected on return, others must be deselected
- * by the caller! (after testing their state)
- *
- * the tree address of the object (from rsrc_gaddr) is passed,
- * together with the originating position of the growing box.
- * a NULL org box will suppress the grow/shrink effects.
- * the index of the exit object is returned.
- *
- */
-
- WORD do_form (taddr,org)
- register OBJECT *taddr; /* form tree address */
- register GRECT *org; /* originating pos of growing box */
-
- {
- register WORD exitobj; /* button used to exit form */
- register char exitform = FALSE; /* hit real exit button? */
- WORD fo_x,fo_y,fo_w,fo_h; /* form position */
-
- form_center(taddr,&fo_x,&fo_y,&fo_w,&fo_h);/* compute position */
-
- /* reserve screen space */
- form_dial(FMD_START,0,0,0,0,fo_x,fo_y,fo_w,fo_h);
-
- if (org != NULL) /* growing boxes wanted? */
- form_dial(FMD_GROW,org->g_x,org->g_y,org->g_w,org->g_h,
- fo_x,fo_y,fo_w,fo_h);
-
- objc_draw(taddr,ROOT,MAX_DEPTH,fo_x,fo_y,fo_w,fo_h);/* draw the form */
-
- while (!exitform) /* loop until real exit */
- {
- exitobj = form_do(taddr,0) & 0x7fff;/* interact with form */
-
- switch (taddr[exitobj].ob_type >> 8)/* get 'user type' of exitobj */
- {
- case 0: /* no user type, real exit */
- exitform = TRUE;
- break;
-
- default: /* some unknown thing */
- break; /* just re-enter */
- }
- }
-
- if (org != NULL) /* shrinking box wanted? */
- form_dial(FMD_SHRINK,org->g_x,org->g_y,org->g_w,org->g_h,
- fo_x,fo_y,fo_w,fo_h);
-
- /* redraw screen */
- form_dial(FMD_FINISH,0,0,0,0,fo_x,fo_y,fo_w,fo_h);
-
- taddr[exitobj].ob_state &= ~SELECTED;/* reset exit to 'not selected' */
- return (exitobj); /* return the exit object# */
- }
- # endif
-
- /* convert GRECT to an array containing 2 vertices */
- /* return a pointer to the result (static area overwritten by each call) */
-
- WORD *rc2pts (grect)
- register GRECT *grect; /* the input points */
-
- {
- static WORD pts[4]; /* the resulting array */
-
- pts[0] = grect->g_x; /* upper left */
- pts[1] = grect->g_y;
-
- pts[2] = grect->g_x + grect->g_w - 1;/* lower right */
- pts[3] = grect->g_y + grect->g_h - 1;
-
- return (pts); /* return a pointer */
- }
-
- /* open main window for this application */
-
- void pop_up ()
-
- {
- GRECT rc; /* work area */
-
- await |= MU_KEYBD; /* also attend keyboard events */
-
- if (window[1].open) /* #1 already opened? */
- {
- wind_set(topwin = window[1].win,WF_TOP);/* top it */
- return;
- }
-
- strcpy(window[1].title," KA9Q Internet Protocol Package ");/* set title */
- window[1].info[0] = 0; /* no info */
-
- window[1].org.g_x = window[0].work.g_x + gr_hwbox;
- window[1].org.g_y = window[0].work.g_y + (gl_mnid + 2) * gr_hhchar;
- window[1].org.g_w = 20 * gr_hwchar;
- window[1].org.g_h = gr_hhchar;
-
- if (!window[1].work.g_w) /* first time? */
- {
- rc.g_w = window[0].work.g_w - gr_hwbox;
- rc.g_h = 10 * gr_hhbox;
- rc.g_x = window[0].work.g_x +
- (window[0].work.g_w - rc.g_w) / 2;
- rc.g_y = window[0].work.g_y + 3 * gr_hhbox;
- wi_align(&rc); /* align on char bound */
- }
- else /* use existing size */
- {
- wind_calc(0,WI_KIND,window[1].work.g_x,
- window[1].work.g_y,
- window[1].work.g_w,
- window[1].work.g_h,
- &rc.g_x,&rc.g_y,&rc.g_w,&rc.g_h);
- }
-
- wi_open(1,WI_KIND,&rc);
- }
- #endif /* GEM */
-
- /* wait for interrupt (?) and return */
- /* in normal version: check for stack overflows, spend time in system */
- /* in desk-accessory version: await next command or timer event */
-
- void eihalt ()
-
- {
- #ifdef GEM
- WORD button; /* current button state */
- WORD bclicked; /* mouse button clicks */
- WORD mx,my; /* mouse position */
- WORD keycode; /* code of pressed key */
- WORD keystat; /* Shift/Ctrl/Alt state */
- WORD msgbuff[8]; /* incoming message buffer */
- WORD d; /* dummy word */
- long count; /* timer millisecond count */
- GRECT rc; /* scratch */
- register WORD event; /* event that occurred */
- register WINDOW *curwin; /* scratch window pointer */
- #endif
-
- #ifndef GEMACC
- if (watchhw)
- Giaccess(watchhw,0x8f); /* put reset on the printerport */
-
- if (STACK[0] != STKMAGIC || /* check the magic numbers */
- STACK[16] != STKMAGIC ||
- STACK[32] != STKMAGIC)
- {
- printf("Stack overflow!\n");
- while (kbread() == -1)
- ;
- doexit(0);
- }
-
- watchcnt = watchnet; /* reset the watchdog */
- if (watchhw)
- Giaccess(0,0x8f); /* put 00 on the printerport */
- #endif
-
- #ifdef GEM
- for (;;)
- {
- if (keyqueue) /* still some key pending? */
- return; /* then process it first */
-
- if (!fastpoll) /* determine polling rate */
- count = 1000; /* slow rate 1 second */
- else
- {
- count = 100; /* fast rate .1 second */
-
- if (!--fastpoll) /* check if next still fast */
- {
- if (window[1].cursor == 2) /* unredrawn info in #1? */
- rq_redraw(window[1].win,&window[1].work);/* draw desired window */
- }
- }
-
- event = evnt_multi(await, /* events we await */
- 2,1,1, /* BUTTON (left only) */
- m1flag,m1.g_x,m1.g_y, /* M1 */
- m1.g_w,m1.g_h,
- m2flag,m2.g_x,m2.g_y, /* M2 */
- m2.g_w,m2.g_h,
- msgbuff, /* MESAG result */
- (WORD) count,(WORD) (count >> 16),/* TIMER */
- &mx,&my, /* BUTTON, M1, M2 result */
- &button,&keystat, /* BUTTON, M1, M2 result */
- &keycode, /* KEYBD result */
- &bclicked); /* BUTTON result */
-
- wind_get(DESK,WF_TOP,&topwin,&d,&d,&d);/* get current top window */
-
- if (event & MU_KEYBD) /* keyboard input */
- {
- keyqueue = keycode; /* save it */
- keyqstat = keystat;
- fastpoll = 50; /* increase activity */
- }
-
- if (event & MU_MESAG) /* incoming message? */
- {
- switch (msgbuff[0]) /* check message type */
- {
- # ifdef GEMPRG
- case MN_SELECTED: /* selected a menu item */
- mn_select(msgbuff[4]); /* process selection */
- menu_tnormal(rs_trindex[MENUBAR],msgbuff[3],TRUE);/* title back to normal */
- break;
- # endif
-
- case WM_REDRAW: /* window redraw request */
- do_redraw(msgbuff[3],(GRECT *) &msgbuff[4]);
- break;
-
- case WM_TOPPED: /* bring it to the top */
- curwin = &window[win[msgbuff[3]]]; /* point to window info */
- if (curwin->cursor == 2 && /* unredrawn info in it? */
- curwin->vert.pos >= curwin->vert.total - curwin->vert.seen)
- rq_redraw(curwin->win,&curwin->work);/* draw desired window */
-
- wind_set(topwin = msgbuff[3],WF_TOP);
- break;
-
- case WM_CLOSED: /* window closed */
- wi_close(msgbuff[3]); /* just close the window */
- break;
-
- case WM_FULLED: /* wants to set to full screen */
- curwin = &window[win[msgbuff[3]]]; /* point to window info */
-
- wind_get(msgbuff[3],WF_CURRXYWH,&rc.g_x,&rc.g_y,&rc.g_w,&rc.g_h);
-
- if (rc_equal(&rc,&curwin->full))/* already fulled? */
- {
- wind_get(msgbuff[3],WF_PREVXYWH,&rc.g_x,&rc.g_y,&rc.g_w,&rc.g_h);
-
- graf_shrinkbox(rc.g_x,rc.g_y,rc.g_w,rc.g_h,
- curwin->full.g_x,curwin->full.g_y,
- curwin->full.g_w,curwin->full.g_h);
-
- wind_set(msgbuff[3],WF_CURRXYWH,rc.g_x,rc.g_y,rc.g_w,rc.g_h);
- }
- else
- {
- graf_growbox(rc.g_x,rc.g_y,rc.g_w,rc.g_h,
- curwin->full.g_x,curwin->full.g_y,
- curwin->full.g_w,curwin->full.g_h);
-
- wind_set(msgbuff[3],WF_CURRXYWH,curwin->full.g_x,curwin->full.g_y,
- curwin->full.g_w,curwin->full.g_h);
- }
-
- wi_getwork(msgbuff[3]); /* get new size */
- sl_update(msgbuff[3]); /* update sliders */
- break;
-
- case WM_ARROWED: /* clicked arrows/scrollbar */
- curwin = &window[win[msgbuff[3]]];/* point to window info */
-
- switch (msgbuff[4]) /* get more detail */
- {
- case 0: /* page up */
- curwin->vert.pos -= curwin->vert.seen;
- break;
-
- case 1: /* page down */
- curwin->vert.pos += curwin->vert.seen;
- break;
-
- case 2: /* row up */
- curwin->vert.pos--;
- break;
-
- case 3: /* row down */
- curwin->vert.pos++;
- break;
-
- case 4: /* page left */
- curwin->hori.pos -= curwin->hori.seen;
- break;
-
- case 5: /* page right */
- curwin->hori.pos += curwin->hori.seen;
- break;
-
- case 6: /* column left */
- curwin->hori.pos--;
- break;
-
- case 7: /* column right */
- curwin->hori.pos++;
- break;
- }
-
- sl_update(msgbuff[3]); /* update sliders */
- rq_redraw(msgbuff[3],&curwin->work);/* draw desired window */
- break;
-
- case WM_HSLID: /* moved horizontal slider */
- curwin = &window[win[msgbuff[3]]];/* point to window info */
- curwin->hori.pos = (long) msgbuff[4] *
- (curwin->hori.total - curwin->hori.seen) / 1000L;
- sl_update(msgbuff[3]); /* update sliders */
- rq_redraw(msgbuff[3],&curwin->work);/* draw desired window */
- break;
-
- case WM_VSLID: /* moved vertical slider */
- curwin = &window[win[msgbuff[3]]];/* point to window info */
- curwin->vert.pos = (long) msgbuff[4] *
- (curwin->vert.total - curwin->vert.seen) / 1000L;
- sl_update(msgbuff[3]); /* update sliders */
- rq_redraw(msgbuff[3],&curwin->work);/* draw desired window */
- break;
-
- case WM_SIZED: /* changed window size */
- if (msgbuff[6] < MIN_WIDTH) /* too small? */
- msgbuff[6] = MIN_WIDTH; /* set to minimal value */
-
- if (msgbuff[7] < MIN_HEIGHT)
- msgbuff[7] = MIN_HEIGHT;
-
- wi_align(&msgbuff[4]); /* align on char bound */
- wind_set(msgbuff[3],WF_CURRXYWH,msgbuff[4],msgbuff[5],
- msgbuff[6],msgbuff[7]);
-
- wi_getwork(msgbuff[3]); /* update pos/size */
- sl_update(msgbuff[3]); /* update sliders */
- break;
-
- case WM_MOVED: /* moved to another pos */
- wi_align(&msgbuff[4]); /* align on char bound */
- wind_set(msgbuff[3],WF_CURRXYWH,msgbuff[4],msgbuff[5],
- msgbuff[6],msgbuff[7]);
-
- wi_getwork(msgbuff[3]); /* update pos/size */
- break;
-
- case WM_NEWTOP: /* placed on top */
- curwin = &window[win[msgbuff[3]]]; /* point to window info */
- if (curwin->cursor == 2 && /* unredrawn info in it? */
- curwin->vert.pos >= curwin->vert.total - curwin->vert.seen)
- rq_redraw(curwin->win,&curwin->work);/* draw desired window */
-
- topwin = msgbuff[3]; /* keep top window handle */
- break;
-
- # ifdef GEMACC
- case AC_OPEN: /* selected accessory */
- if (msgbuff[4] == gl_mnid) /* doc says it's in word 3! */
- pop_up(); /* pop-up our main window */
- break;
-
- case AC_CLOSE: /* removed accessory */
- if (msgbuff[3] == gl_mnid) /* make sure it's for me! */
- {
- for (d = 1; d < USEWIN; d++)/* yep, so all user windows */
- window[d].open = FALSE;/* have been closed and deleted */
-
- for (d = 1; d < MAXWIN; d++)/* also get rid of handle info */
- win[d] = 0;
-
- topwin = -1; /* WE are not on top anymore! */
- await &= ~MU_KEYBD; /* keyboard not of interest */
- }
- break;
- # endif
- }
-
- fastpoll = 50; /* message came in, be active */
- }
-
- if (event & MU_TIMER) /* time expired */
- return; /* continue in KA9Q code */
- }
- #else /* not GEM */
- /* spend some time in system, mainly for profiling */
- Vsync();
- Vsync();
- #endif
- }
-
- #ifdef GEMACC
- /* desk accessories must never exit... */
-
- exit (val)
- int val;
-
- {
- printf("\nAttempt to exit(%d)\n",val);
-
- for (;;)
- {
- keyqueue = 0; /* force action */
- eihalt();
- }
- }
-
- # ifdef MWC
- /* the allocation routines are not designed for desktop accessory use... */
- /* define a replacement handler for low-level allocation */
-
- extern int end[]; /* end of program */
- static long Memtop = end; /* current end of alloced space */
- static char Mallocspace[50000L]; /* fixed area for dynamic allocation */
- static long Mallocused = 0; /* amount of area actually used now */
-
- long lsbrk (incr)
- register long incr; /* storage increment */
-
- {
- register long rv; /* return value */
-
- if (incr < 0) /* decreasing top? */
- return (-1L); /* not supported... */
-
- if (incr == 0) /* query? */
- return (Memtop); /* return current top */
-
- incr = (incr + 1) & 0xfffffffeL; /* incr must be even */
- rv = (long) (Mallocspace + Mallocused);/* compute address of new space */
-
- if ((rv + incr) > (long) (Mallocspace + sizeof(Mallocspace)))
- return (-1L); /* return -1 on failure */
-
- Mallocused += incr; /* reserve the space */
- Memtop = rv + incr; /* set new top */
-
- return (rv); /* and return the pointer */
- }
- # endif /* MWC */
- #endif /* GEM */
-
- /* return the amount of free memory (= available from TOS) */
-
- static long freemem ()
-
- {
- #ifdef GEMACC
- return ((long) sizeof(Mallocspace) - Mallocused);
- #else
- long size;
- char *addr;
-
- if ((size = (long) Malloc(-1L)) < 256L) /* get largest available block */
- return (size); /* when <= 256, stop looking */
-
- addr = (char *) Malloc(size); /* acquire the specified block */
- size += freemem(); /* add this + any other blocks */
- Mfree(addr); /* return the allocated block */
- return (size); /* return total size */
- #endif
- }
-
-
- /* Print free list map, when arg given also show free block sizes */
- /* when numeric arg given, alloc/free that number of bytes */
-
- int
- memstat (argc,argv)
- int argc;
- char *argv[];
-
- {
- #ifdef MWC
- /* This is severely dependent on the inner workings of the Mark Williams */
- /* allocation routines...... */
-
- struct memblock {
- long size;
- struct memblock *next;
- };
- extern struct memblock *_a_scanp;
- register struct memblock *mp,*nmp;
- register long bsize;
- register int bmode;
- int nblocks[2];
- long nbytes[2];
- long mxsize[2];
- int nchunks;
- char *lmalloc();
-
- if (argc > 1 && isdigit(argv[1][0])) {
- if ((mp = (struct memblock *) lmalloc(atol(argv[1]))) == 0) {
- printf("malloc failure\n");
- return 1;
- }
-
- free((char *) mp);
- return 0;
- }
-
- nblocks[0] = nblocks[1] = nchunks = 0;
- nbytes[0] = nbytes[1] = mxsize[0] = mxsize[1] = 0;
- if (argc > 1)
- printf("free block sizes:\n");
-
- mp = _a_scanp; /* get start of blocklist */
- do {
- if (mp->size == 0){ /* zero size is a chain item */
- nchunks++; /* count them */
- mp = mp->next;
- } else {
- if ((bsize = mp->size & ~1L) < 0)/* blocksize, always even */
- break; /* quit when <0 (panic) */
-
- if (bmode = mp->size & 1) /* 0=alloced, 1=free */
- /* when free, check if next also free */
- while ((nmp = (struct memblock *) ((char *) mp + bsize)) != _a_scanp &&
- (nmp->size & 1))
- /* join next (free) block with this one */
- mp->size = (bsize += nmp->size & ~1L) | 1;
-
- nblocks[bmode]++;
- nbytes[bmode] += bsize;
- if (bsize > mxsize[bmode])
- mxsize[bmode] = bsize;
- if (bmode && argc > 1)
- printf("%8ld",bsize - sizeof(long));
-
- ((char *) mp) += bsize; /* advance ptr to next */
- }
- } while (mp != _a_scanp && nchunks < 1000); /* continue until complete round */
-
- if (argc > 1)
- printf("\n");
-
- if (bsize < 0)
- printf("panic: size of at least one block <0!! (%ld @ %06x)\n",
- mp->size,&mp->next);
-
- printf("%7ld bytes claimed in %d chunks\n",nbytes[0] + nbytes[1],nchunks);
- printf("%7ld bytes available from system\n",freemem());
- for (bmode = 0; bmode < 2; bmode++)
- printf("%7ld bytes %s in %3d blocks (largest %ld)\n",
- nbytes[bmode],(bmode? "free" : "used"),
- nblocks[bmode],mxsize[bmode] - sizeof(long));
- #endif
- return 0;
- }
-
- #ifndef GEMACC
- /* called at each timer tick. decement a counter and RESET if it */
- /* reaches zero. the processor is already in supervisor mode. */
-
- static void watchtick (timer_ms)
- unsigned int timer_ms;
-
- {
- if (watchcnt != 0 && --watchcnt == 0){
- *((long *) 0x3fc) = 0x53574154L; /* set signature (see log proc) */
- (**((int (**)()) 4L))(); /* jump via RESET vector */
- }
-
- (*orgtick)(timer_ms); /* call original handler */
- }
- #endif
-
- /* reboot the system. this is used when the SYS_RESET function code */
- /* is used on the "remote" server */
-
- sysreset()
-
- {
- Super(NULL); /* switch to supervisor mode */
- *((long *) 0x3fc) = 0x0L; /* remove signature (see log proc) */
- (**((int (**)()) 4L))(); /* jump via RESET vector */
- }
-
- #ifdef MWC
- /* Select screen output mode */
- int
- doscreen (argc,argv)
- int argc;
- char *argv[];
-
- {
- int conputc(); /* console putc routine */
-
- fflush(stdout); /* first flush any pending output */
-
- switch (argv[1][0]) /* select on specified mode */
- {
- # ifndef GEM
- case 'b': /* using BIOS output */
- screenmode = SCRBIOS;
- stdout->_pt = conputc;
- break;
- # endif
-
- case 'd': /* using direct out to video */
- screenmode = SCRDIR;
- # ifndef GEM
- linea0(); /* get line A info */
- logbase = Logbase(); /* read logical screen base */
- stdout->_pt = conputc;
- # endif
- break;
-
- case 't': /* using output via TOS */
- screenmode = SCRTOS;
- # ifndef GEM
- stdout->_pt = _fputt;
- # endif
- break;
-
- default: /* unrecognized */
- return -1; /* cmdparse will print options */
- }
-
- return 0;
- }
-
- /* utility routines for output redirection */
-
- # ifndef GEM
- /* put byte on AUX and/or console */
- int conputc(c,outfile)
- int c;
- FILE *outfile;
-
- {
- register char *set,*screen;
-
- if (outfile == stdout)
- {
- if (auxcon & AUXCOUT) /* output to AUX? */
- {
- if (c == '\n')
- Bconout(1,auxotrn['\r']);
-
- Bconout(1,auxotrn[uchar(c)]);
- }
-
- if (auxcon & AUXCNOT) /* no output to screen? */
- return c;
-
- if (cursor) /* cursor still on? */
- {
- cursor = 0;
- Bconout(2,'\033'); /* switch it off */
- Bconout(2,'f');
- }
-
- switch (screenmode)
- {
- case SCRBIOS: /* output via BIOS */
- if (c == '\n')
- Bconout(2,'\r');
-
- Bconout(2,c);
- return c;
-
- case SCRDIR:
- switch (c) /* interpret char */
- {
- case '\n': /* new line */
- Bconout(2,'\r'); /* also does a CR */
- if (V_CUR_CY == V_CEL_MY) /* check for last screen line */
- {
- while (Kbshift(-1) & 0x08) /* Alternate key pressed? */
- Vsync(); /* then hold screen */
-
- do_scroll(logbase); /* move it up by one line */
- V_CUR_CY--; /* and tell that to line A */
- }
-
- case '\a': /* bell */
- case '\b': /* backspace */
- case '\t': /* tab */
- case '\r': /* carriage return */
- Bconout(2,c);
- break;
-
- case '\0': /* NUL */
- break;
-
- default:
- set = (char *) V_FNT_AD + uchar(c);
- screen = (char *) V_CUR_AD; /* cursor address */
-
- switch (VPLANES) /* depending on video mode... */
- {
- case 1:
- screen[ 0 * 80] = set[ 0 * 256]; /* blit the single character */
- screen[ 1 * 80] = set[ 1 * 256];
- screen[ 2 * 80] = set[ 2 * 256];
- screen[ 3 * 80] = set[ 3 * 256];
- screen[ 4 * 80] = set[ 4 * 256];
- screen[ 5 * 80] = set[ 5 * 256];
- screen[ 6 * 80] = set[ 6 * 256];
- screen[ 7 * 80] = set[ 7 * 256];
- screen[ 8 * 80] = set[ 8 * 256];
- screen[ 9 * 80] = set[ 9 * 256];
- screen[10 * 80] = set[10 * 256];
- screen[11 * 80] = set[11 * 256];
- screen[12 * 80] = set[12 * 256];
- screen[13 * 80] = set[13 * 256];
- screen[14 * 80] = set[14 * 256];
- screen[15 * 80] = set[15 * 256];
-
- if (V_CUR_CX < V_CEL_MX)
- {
- V_CUR_AD++; /* simply increment addr */
- V_CUR_CX++; /* and cursor position */
- }
- else
- {
- Bconout(2,'\r'); /* wrap cursor */
- if (V_CUR_CY == V_CEL_MY)
- {
- do_scroll(logbase);
- V_CUR_CY--;
- }
- Bconout(2,'\n');
- }
- break;
-
- case 2:
- screen[0 * 160] = screen[0 * 160 + 2] = set[0 * 256];
- screen[1 * 160] = screen[1 * 160 + 2] = set[1 * 256];
- screen[2 * 160] = screen[2 * 160 + 2] = set[2 * 256];
- screen[3 * 160] = screen[3 * 160 + 2] = set[3 * 256];
- screen[4 * 160] = screen[4 * 160 + 2] = set[4 * 256];
- screen[5 * 160] = screen[5 * 160 + 2] = set[5 * 256];
- screen[6 * 160] = screen[6 * 160 + 2] = set[6 * 256];
- screen[7 * 160] = screen[7 * 160 + 2] = set[7 * 256];
-
- if (V_CUR_CX < V_CEL_MX)
- {
- V_CUR_AD += (V_CUR_CX & 1)? 3 : 1;
- V_CUR_CX++;
- }
- else
- {
- Bconout(2,'\r'); /* wrap cursor */
- if (V_CUR_CY == V_CEL_MY)
- {
- do_scroll(logbase);
- V_CUR_CY--;
- }
- Bconout(2,'\n');
- }
- break;
- }
- break;
- }
- return c;
- }
- }
-
- return (_fputt(c,outfile)); /* call original out char routine */
- }
- # endif
-
- /* route standard I/O to the AUX port, to facilitate control via a */
- /* terminal connected to this port */
- /* Usage: auxcon <io code> [<baudrate> [7|8 [noflow]]] */
- /* <io code> is 10 (input) | 01 (output) | 02 (no screen output) */
- int
- doauxcon(argc,argv)
- int argc;
- char *argv[];
- {
- register int i;
- int sp = -1; /* default = unchanged speed */
- int ucr = 0x88; /* 8bit, no parity, 1 stopbit */
- int flow = 1; /* default = XON/XOFF flow ctrl */
-
- # ifndef GEM
- stdout->_pt = (screenmode == SCRTOS)? _fputt : conputc;
- # endif
-
- if ((auxcon = htoi(argv[1])) == 0) /* convert arg, 0 = off */
- return 0;
-
- for (i = 0; i < nasy; i++)
- if (asy[i].addr == RS232)
- {
- auxcon = 0;
- printf("AUX: already in use for SLIP or KISS\n");
- return 1;
- }
-
- for (i = 0; i < 256; i++) /* init translate tables */
- auxotrn[i] = auxitrn[i] = i;
-
- auxotrn[0x11] = auxotrn[0x13] = '.'; /* inhibit XON and XOFF */
-
- /* set some keycodes. these values are especially good for the */
- /* EPSON PX-8. this should be made variable for other terminals. */
-
- auxitrn[0x03] = -2; /* STOP = command mode (F10) */
- auxitrn[0x0b] = 0x12; /* HOME = retype line (^R) */
- auxitrn[0x12] = -12; /* INS = insert mode */
- auxitrn[0x1c] = -16; /* RIGHT */
- auxitrn[0x1d] = -17; /* LEFT */
- auxitrn[0x1e] = -19; /* UP */
- auxitrn[0x1f] = -14; /* DOWN */
-
- if (argc > 2)
- switch (atoi(argv[2]))
- {
- case 19200: sp = 0; break;
- case 9600: sp = 1; break;
- case 4800: sp = 2; break;
- case 3600: sp = 3; break;
- case 2400: sp = 4; break;
- case 1200: sp = 7; break;
- case 600: sp = 8; break;
- case 300: sp = 9; break;
- default:
- printf("auxcon: unsupported speed %s (speed unchanged)\n",argv[2]);
- break;
- }
-
- if (argc > 3 && argv[3][0] == '7')
- {
- ucr = 0x0ae; /* 7 bit, even parity, 1 stopbit */
-
- for (i = 128; i < 256; i++)
- {
- auxotrn[i] = '.';
- auxitrn[i] = auxitrn[i - 128];
- }
- }
-
- if (argc > 4 && argv[4][0] == 'n')
- flow = 0; /* no flow control */
-
- Rsconf(sp,flow,ucr,0x01,0x01,0x00); /* set the MFP serial channel */
- # ifndef GEM
- if (auxcon & AUXCOUT) /* output to AUX selected? */
- stdout->_pt = conputc; /* set replacement "put char" routine */
- # endif
- return 0;
- }
- #endif
-
-
- /* Print or Set the date and time */
-
- dodate(argc,argv)
- int argc;
- char *argv[];
- {
- long tloc;
- register char *p;
- int y,m,d,h,n,s;
- extern long starttime;
- #ifdef MWC
- extern long _boottime;
- #endif
-
- if (argc < 2) {
- time(&tloc);
- printf("%s",ctime(&tloc));
- return 0;
- }
-
-
- if (*(p = argv[1]) == 's') { /* starttime */
- printf("starttime: %s",ctime(&starttime));
- return 0;
- }
-
- #ifdef MWC
- if (*p == 'b') { /* boottime */
- time(&tloc);
- printf("boottime: %s",ctime(&_boottime));
- return 0;
- }
- #endif
-
- if (strlen(p) != 10 && strlen(p) != 12)
- return -1;
- while (*p)
- if (!isdigit(*p++))
- return -1;
-
- p = argv[1];
- m = 10 * p[0] + p[1] - 11 * '0';
- d = 10 * p[2] + p[3] - 11 * '0';
- h = 10 * p[4] + p[5] - 11 * '0';
- n = 10 * p[6] + p[7] - 11 * '0';
- s = 10 * p[8] + p[9] - 11 * '0';
- if (p[10]) {
- if ((y = 10 * p[10] + p[11] - 11 * '0' + 1900) < 1980)
- y += 100;
- } else
- y = ((Tgetdate() >> 9) & 0x7f) + 1980;
-
- if (Tsettime((h << 11) | (n << 5) | (s >> 1)) ||
- Tsetdate(((y - 1980) << 9) | (m << 5) | d))
- return -1;
-
- Settime(((long) (y - 1980) << 25) | ((long) m << 21) | ((long) d << 16) |
- ((long) h << 11) | (n << 5) | (s >> 1));
-
- #ifdef MWC
- _boottime = 0; /* reset MW's idea of time */
- #endif
- return 0;
- }
-
- /* Spawn subshell */
- /* extension: "shell =name" sets the program to run as a shell */
-
- doshell(argc,argv)
- int argc;
- char *argv[];
- {
- static char command[80] = "COMMAND.PRG";
- #ifndef GEM
- char tail[128], *p = tail + 1,**envp;
- int arg,len;
- long ret;
- int curdrive;
- char curdir[66];
- #endif
-
- if (argc == 2 && argv[1][0] == '=')
- {
- strcpy(command,argv[1] + 1);
- return 0;
- }
-
- #ifdef GEM
- printf("No shell in GEM version...\n");
- #else
- curdrive = Dgetdrv(); /* get current drive (0,1,...) */
-
- if (Dgetpath(tail,0) == 0){ /* get current dir */
- sprintf(curdir,"%c:%s%s",(char) curdrive+'A',
- (*tail? "" : "\\"),tail);
- }
-
- tail[0] = 0;
-
- for (arg = 1; arg < argc; arg++)
- {
- len = strlen(argv[arg]);
-
- if ((len + tail[0]) < 127)
- {
- if (tail[0])
- {
- *p++ = ' ';
- tail[0]++;
- }
-
- strcpy(p,argv[arg]);
- p += len;
- tail[0] += len;
- }
- else
- break;
- }
-
- # ifdef SERVERS
- if (logfp != NULLFILE) /* logging to file? */
- fclose(logfp);
- # endif
-
- # ifdef TRACE
- if (trfp != stdout) /* trace to file? */
- fclose(trfp); /* close it during shell exec */
- # endif
-
- Bconout(2,'\033'); /* make sure cursor is ON */
- Bconout(2,'e');
- cursor = 1;
-
- watchcnt = watchsh; /* set SHELL watchdog time */
-
- if ((envp = make_env()) != NULLCHRP)
- ret = Pexec(0,command,tail,envp[0]);
- else
- ret = Pexec(0,command,tail,NULLCHRP);
-
- free_env();
-
- Dsetdrv(curdrive); /* reset current directory */
- Dsetpath(curdir);
-
- # ifdef SERVERS
- if (logfp != NULLFILE) /* re-open logfile if it was open */
- logfp = fopen(logname,"a+");
- # endif
-
- # ifdef TRACE
- if (trfp != stdout) /* re-open tracefile if not stdout */
- if ((trfp = fopen(trname,"a+")) == NULLFILE)
- trfp = stdout;
- # endif
-
- Bconout(2,'\033'); /* make sure cursor is ON */
- Bconout(2,'e');
- Bconout(2,'\033'); /* autoWRAP ON */
- Bconout(2,'v');
-
- if (ret < 0)
- {
- printf("%s: cannot execute\n",command);
- return -1;
- }
- #endif
-
- return 0;
- }
-
- /* control the watchdog function */
-
- dowatchdog (argc,argv)
- int argc;
- char *argv[];
- {
- #ifndef GEMACC
- unsigned int timer_ms = Tickcal();
-
- switch (argc)
- {
- case 4:
- watchhw = atoi(argv[3]) & 0xff;
- case 3:
- watchsh = (atol(argv[2]) * 1000) / timer_ms;
- case 2:
- watchnet = (atol(argv[1]) * 1000) / timer_ms;
- break;
- case 1:
- printf("NET=%ld SHELL=%ld HW=%u\n",
- (watchnet * timer_ms) / 1000,
- (watchsh * timer_ms) / 1000,watchhw);
- break;
- }
- #endif
- return 0;
- }
-
- /* interrupt latency measurement (for testing and optimizing purposes) */
-
- #define MODE 4
- #define PRESCALE 50
- #define CLOCK 2457600L
-
- unsigned long latency[256];
- static int lat_active = 0;
-
- static void lat_stop ()
-
- {
- Xbtimer(0,0,0,NULLVFP); /* stop timer & remove handler */
- }
-
- static void lat_start ()
-
- {
- extern void lathandler();
-
- Xbtimer(0,MODE,255,lathandler); /* init timer and start it */
- }
-
- /* start/stop/display latency measurement */
-
- dolatency (argc,argv)
- int argc;
- char *argv[];
- {
- switch (tolower(argv[1][0]))
- {
- case 'n': /* stop measurement */
- lat_stop();
- lat_active = 0;
- break;
-
- case 'y': /* clear & start measurement */
- lat_stop(); /* first stop it for safety */
- memset(latency,0,sizeof(latency)); /* clear the tallies */
- lat_start(); /* start measurement */
- lat_active = 1;
- break;
-
- case 'r': /* show raw data */
- lat_raw();
- break;
-
- case 's': /* show status (results) */
- if (!lat_active) {
- printf("latency measurement not active\n");
- break;
- }
- lat_stop();
- lat_status();
- lat_start();
- break;
-
- default:
- return -1;
- }
-
- return 0;
- }
-
- static char *pltime (timer)
- unsigned int timer;
-
- {
- static char buf[80];
-
- timer = 255 - timer; /* compute elapsed time */
-
- sprintf(buf,"%6lu us",(1000000L*PRESCALE*timer)/CLOCK);
-
- if (timer != 0)
- sprintf(buf + 9,", %6lu/s, %6lu bps",CLOCK/((long) PRESCALE*timer),
- (CLOCK*8)/((long) PRESCALE*timer));
-
- return buf;
- }
-
- static void lat_raw ()
-
- {
- unsigned int i = 255;
-
- do
- {
- if (latency[i] != 0)
- printf("%9lu * %s\n",latency[i],pltime(i));
- }
- while (i-- != 0);
- }
-
- static void lat_status ()
-
- {
- unsigned int i,j;
- unsigned int lng,max;
- unsigned long maxv,totl,ttl,lim;
-
- for (lng = 0; lng < 256; lng++) /* find longest latency */
- if (latency[lng] != 0)
- break;
-
- maxv = totl = 0;
-
- for (i = lng; i < 256; i++)
- {
- totl += latency[i]; /* count total number of ticks */
-
- if (latency[i] > maxv) /* record largest number */
- {
- maxv = latency[i]; /* found a larger number! */
- max = i;
- }
- }
-
- printf("%lu samples\n\n",totl); /* print total number of samples */
-
- printf("normal: %s (%lu%%)\n",pltime(max),maxv / (totl / 100L));
- printf("longest: %s (%lu)\n\n",pltime(lng),latency[lng]);
-
- lim = 1;
-
- for (j = 1; j < 10; j++) /* 10^1 .. 10^9 */
- {
- lim *= 10;
-
- if ((maxv = (totl / lim)) == 0) /* total #ticks / 10^n */
- break;
-
- ttl = 0;
-
- for (i = 0; i < 256; i++)
- if ((ttl += latency[i]) > maxv)
- break;
-
- printf("<1 in 10^%d longer than %s\n",j,pltime(i));
- }
- }
-
- #if (defined(MWC) && (MWC < 306))
- /* Mark Williams C has a bug that influences '>> 16' constructs... */
- /* when you shift a long value by exactly 16 bits, the compiler */
- /* cleverly codes a "swap" and "ext.w", it should have been "ext.l" */
- /* we define this variable to generate less-optimized code (see global.h) */
- /* The bug was fixed in 3.0.6 (according to Howard Chu) */
-
- int Sixteen = 16; /* shift for hiword... */
- #endif
-
-